package com.miniapp.service.impl;


import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.vioao.wechat.api.component.wxa.CodeApi;
import com.github.vioao.wechat.bean.entity.component.wxa.Commit;
import com.github.vioao.wechat.bean.entity.component.wxa.SubmitAudit;
import com.github.vioao.wechat.bean.response.BaseResponse;
import com.github.vioao.wechat.bean.response.component.wxa.GetCategoryResponse;
import com.github.vioao.wechat.bean.response.component.wxa.GetPageResponse;
import com.miniapp.conifg.wechatOpen.WechatDomainProperties;
import com.miniapp.dto.ExtJsonDTO;
import com.miniapp.dto.PageDTO;
import com.miniapp.dto.SimpleSearchDTO;
import com.miniapp.dto.form.MiniAppCreateDTO;
import com.miniapp.entity.*;
import com.miniapp.entity.enums.MiniProductPayStatus;
import com.miniapp.entity.enums.MiniVersionStatus;
import com.miniapp.exception.RRException;
import com.miniapp.mapper.*;
import com.miniapp.service.*;
import com.miniapp.utils.BaseUtils;
import com.miniapp.utils.DateUtils;
import com.miniapp.utils.R;
import com.miniapp.utils.RequestHelper;
import me.chanjar.weixin.common.exception.WxErrorException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import weixin.popular.api.WxaAPI;
import weixin.popular.bean.wxa.ModifyDomain;
import weixin.popular.bean.wxa.ModifyDomainResult;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


@Service
public class MiniUserProductServiceImpl extends BaseServiceImpl<MiniUserProductMapper,MiniUserProductEntity>  implements MiniUserProductService {

    public static final Logger logger = LoggerFactory.getLogger(MiniUserProductServiceImpl.class);

    @Autowired
    private MiniProductService miniProductService;
    @Autowired
    private MiniVersionLogService miniVersionLogService;
    @Autowired
    private MiniUserService miniUserService;
    @Resource
    private MiniPayLogService miniPayLogService;
    @Autowired
    private MiniUserTemplateService miniUserTemplateService;
    @Autowired
    private MiniTemplateService miniTemplateService;
    @Autowired
    private MiniProductPriceService miniProductPriceService;
    @Autowired
    protected WechatDomainProperties wechatDomainProperties;
    @Autowired
    protected WxOpenService wxOpenService;


    @Override
    public PageDTO<MiniUserProductEntity> findPageBySql(SimpleSearchDTO simpleSearchDTO) {

        Page<MiniUserProductEntity> page = new Page<>(simpleSearchDTO.getPageIndex(), simpleSearchDTO.getPageSize());
        page.setRecords(this.baseMapper.findPageBySql(page, this.createQueryWrapper(simpleSearchDTO)));
        return new PageDTO<>(page);
    }

    @Override
    public MiniUserProductEntity findByWxAppid(String authorizerAppid) {
        return baseMapper.selectOne(new QueryWrapper<MiniUserProductEntity>().eq("wx_appid",authorizerAppid));
    }

    @Override
    public List<MiniUserProductEntity> findByBuyUserId(Long userId) {
        return baseMapper.selectList(new QueryWrapper<MiniUserProductEntity>().eq("buy_user_id",userId).orderByDesc("create_time"));
    }

    @Override
    public R createMiniapp(MiniAppCreateDTO miniAppCreateDTO, Long userId, HttpServletRequest request) {
        //校验用户余额
        MiniUserEntity userEntity = miniUserService.getById(userId);
        if (BaseUtils.isEmpty(userEntity)){
            return R.error("用户登陆异常");
        }
        MiniProductEntity miniProduct = miniProductService.getById(miniAppCreateDTO.getProductId());
        if (BaseUtils.isEmpty(miniProduct)){
            return R.error("用户参数异常");
        }
        MiniProductPriceEntity priceEntity = miniProductPriceService.getById(miniAppCreateDTO.getPriceId());
        if (BaseUtils.isEmpty(priceEntity)){
            return R.error("用户参数异常");
        }
        if (userEntity.getBalance().compareTo(priceEntity.getPrice())<0){
            return R.error("用户余额不足");
        }


        MiniUserProductEntity miniUserProduct = new MiniUserProductEntity();
        String appid = BaseUtils.get32UUID();
        miniUserProduct.setBuyTime(new Date());
        miniUserProduct.setBuyUserId(userId);
        miniUserProduct.setProductId(miniAppCreateDTO.getProductId());
        miniUserProduct.setProductPriceId(miniAppCreateDTO.getPriceId());
        miniUserProduct.setEdition(miniProduct.getEdition());
        miniUserProduct.setName(miniAppCreateDTO.getName());
        miniUserProduct.setExpirationTime(BaseUtils.getMonthCount(new Date(),1));
        miniUserProduct.setAppid(appid);
        miniUserProduct.setPayStatus(MiniProductPayStatus.TESTING);
        miniUserProduct.setStatus(MiniVersionStatus.DOWN);
        baseMapper.insert(miniUserProduct);
        this.updateRenew(miniUserProduct,request,userId);
        //创建默认模版
        MiniTemplateEntity miniTemplateEntity = miniTemplateService.findByProductIdAndDefault(miniAppCreateDTO.getProductId(),1);
        miniUserTemplateService.create(miniTemplateEntity.getId(),appid);

        return R.ok().put("appid",miniUserProduct.getAppid());
    }

    @Override
    public MiniUserProductEntity findByAppid(String appid) {

        return baseMapper.selectOne(new QueryWrapper<MiniUserProductEntity>().eq("appid",appid));
    }

    @Override
    public MiniUserProductEntity findByWxGhId(String wxGxId) {

        return baseMapper.selectOne(new QueryWrapper<MiniUserProductEntity>().eq("wx_gh_id",wxGxId));
    }

    @Override
    @Transactional
    public R changeStatus(MiniUserProductEntity miniUserProduct, MiniVersionStatus key) {

        MiniVersionLogEntity miniVersionLog = new MiniVersionLogEntity();
        miniVersionLog.setEdition(miniUserProduct.getEdition());
        miniVersionLog.setStatus(key);
        miniVersionLog.setUserProductId(miniUserProduct.getId());

        miniVersionLogService.save(miniVersionLog);

        miniUserProduct.setStatus(key);
        if (key.equals(MiniVersionStatus.DOWN)){
            miniUserProduct.setWxGhId("");
            miniUserProduct.setWxAppid("");
        }
        baseMapper.updateById(miniUserProduct);

        return R.ok();
    }

    @Override
    public boolean isBand(String wxAppID, Long id) {

        List<MiniUserProductEntity> miniUserProducts =  baseMapper.selectList(new QueryWrapper<MiniUserProductEntity>()
                .eq("wx_appid",wxAppID).eq("status",MiniVersionStatus.DOWN).ne("id",id));
        if (miniUserProducts.size()>0){
            return false;
        }
        return true;
    }

    /**
     * 用户续费
     * @param dto
     * @param request
     * @param userId
     */
    @Override
    @Transactional
    public R updateRenew(MiniUserProductEntity dto, HttpServletRequest request, Long userId) {

        MiniUserProductEntity miniUserProduct =baseMapper.selectById(dto.getId());
        if(BaseUtils.isEmpty(miniUserProduct)){
            return R.error("找不到该小程序");
        }
        MiniProductPriceEntity  priceEntity = miniProductPriceService.getById(dto.getProductPriceId());

        if(BaseUtils.isNotEmpty(miniUserProduct)){
            // 扣除用户余额
            // 谁操作扣除谁的余额
            MiniUserEntity miniUser = miniUserService.getById(userId);
            if(BaseUtils.isNotEmpty(miniUser)){

                //用户扣除后余额
                if (miniUser.getBalance().compareTo(priceEntity.getPrice())<0){
                    return R.error("余额不足");
                }
                miniUserService.updateBalance(userId,userId,priceEntity.getPrice().multiply(new BigDecimal(-1)));

                //保存操作日志
                MiniPayLogEntity miniPayLogEntity = new MiniPayLogEntity();
                miniPayLogEntity.setPrice(priceEntity.getPrice());
                miniPayLogEntity.setPriceType(priceEntity.getType());
                miniPayLogEntity.setUserProductId(miniUserProduct.getProductId());
                miniPayLogEntity.setUserProductName(miniUserProduct.getProductName());
                miniPayLogEntity.setOperate(miniUser.getName());
                miniPayLogEntity.setOperateIp(RequestHelper.getRemoteHost(request));

                miniPayLogService.save(miniPayLogEntity);

            }else {
                return R.error("找不到该小程序");
            }
            // 更新到期时间
            miniUserProduct.setExpirationTime(DateUtils.addDateDays(miniUserProduct.getExpirationTime(),priceEntity.getDay()));
            // 更新累计消费
            miniUserProduct.setAddMoney(miniUserProduct.getAddMoney().add(priceEntity.getPrice()));
            //更新支付状态
            miniUserProduct.setPayStatus(MiniProductPayStatus.PAYED);
            miniUserProduct.setProductPriceId(dto.getProductPriceId());

            baseMapper.updateById(miniUserProduct);
        }
        return  R.ok();
    }


    @Override
    public R upgrade(Long[] ids) {
        for(Long id :ids){
            MiniUserProductEntity miniUserProduct = baseMapper.selectById(id);
            if (BaseUtils.isNotEmpty(miniUserProduct)){
                this.commitByAppid(miniUserProduct.getAppid());
            }
        }
        return R.ok("升级成功");
    }

    @Override
    public R commitByAppid(String appid) {

        MiniUserProductEntity miniUserProduct = this.findByAppid(appid);
        String accessToken ;
        try{
            accessToken = wxOpenService.getWxOpenComponentService().getAuthorizerAccessToken(miniUserProduct.getWxAppid(),true);
        }catch (WxErrorException e){
            return R.error("获取授权失败，请检查！");
        }
        if (BaseUtils.isEmpty(miniUserProduct)){
            throw new RRException("访问异常");
        }
        MiniUserTemplateEntity miniUserTemplate  = miniUserTemplateService.findByUsedAndAppid(appid);
        if (BaseUtils.isEmpty(miniUserTemplate)){
            return R.error("请先配置模版");
        }
        //            //设置小程序服务域名
        ModifyDomain domain = new ModifyDomain("set",wechatDomainProperties.getRequestdomain(),
                wechatDomainProperties.getWsrequestdomain(),wechatDomainProperties.getUploaddomain(),
                wechatDomainProperties.getDownloaddomain());

        ModifyDomainResult modifyDomainResponse = WxaAPI.modify_domain(accessToken,domain);
        if(!modifyDomainResponse.isSuccess()){
            return R.error("设置服务域名失败"+modifyDomainResponse.getErrmsg());
        }
//      代码提交
        ExtJsonDTO extJsonDTO = new ExtJsonDTO();
        extJsonDTO.setExtEnable(true);
        extJsonDTO.setExtAppid(miniUserProduct.getWxAppid());
        //是否自动提交审核
        extJsonDTO.setDirectCommit(true);
        extJsonDTO.addExt("appid",miniUserProduct.getAppid());
        extJsonDTO.addWindow("backgroundTextStyle","light");
        extJsonDTO.addWindow("navigationBarBackgroundColor","#ffffff");
        extJsonDTO.addWindow("navigationBarTitleText",miniUserProduct.getName());
        extJsonDTO.addWindow("navigationBarTextStyle","black");
        extJsonDTO.addNetworkTimeout("request",10000);
        extJsonDTO.addNetworkTimeout("downloadFile",10000);
        logger.info(JSON.toJSONString(extJsonDTO));
        String extStr = JSON.toJSONString(extJsonDTO);
        Commit.CommitBuilder commit = Commit.builder().extJson(extStr)
                .templateId(miniUserProduct.getWxTmpId())
                .userVersion(miniUserProduct.getEdition())
                .userDesc(miniUserProduct.getName());
        BaseResponse baseResponse = CodeApi.commit(accessToken,commit.build());
        logger.info("提交审核"+ baseResponse.toString());
        if (!baseResponse.isSuccess()){
            return  R.error("代码提交失败!"+baseResponse.getErrmsg());
        }
        //代码审核
        //获取小程序的第三方提交代码的页面配置
        GetPageResponse getPageResponse = CodeApi.getPage(accessToken);
        logger.info("页面配置"+getPageResponse.toString());
        if (!getPageResponse.isSuccess()){
            return  R.error("获取小程序页面配置失败!"+getPageResponse.getErrmsg());
        }

        //获取授权小程序帐号的可选类目
        GetCategoryResponse getCategoryResponse = CodeApi.getCategory(accessToken);
        logger.info("可选类目"+getCategoryResponse.toString());
        if (!getCategoryResponse.isSuccess()){
            return  R.error("获取小程序类目失败!"+getCategoryResponse.getErrmsg());
        }

        if (getCategoryResponse.getCategoryList().size() == 0){
            return R.error("获取小程序类目失败");
        }

        SubmitAudit.Item item  = SubmitAudit.Item.builder()
                .firstClass(getCategoryResponse.getCategoryList().get(0).getFirstClass())
                .secondClass(getCategoryResponse.getCategoryList().get(0).getSecondClass())
                .firstId(getCategoryResponse.getCategoryList().get(0).getFirstId())
                .secondId(getCategoryResponse.getCategoryList().get(0).getSecondId())
                .address(getPageResponse.getPageList().get(0))
                .title(miniUserProduct.getName()).build();
        List<SubmitAudit.Item> items = new ArrayList<>();
        items.add(item);
        SubmitAudit submitAudit = new SubmitAudit(items);
        BaseResponse baseResponse2  = CodeApi.submitAudit(accessToken,submitAudit);

        if (baseResponse2.isSuccess()){
            this.changeStatus(miniUserProduct,MiniVersionStatus.AUDIT);
            return R.ok();
        }else{
            return R.error(baseResponse2.getErrcode(),baseResponse2.getErrmsg());
        }
    }
}
